package org.os.framework.crypto.algorithm;

import lombok.SneakyThrows;

import org.bouncycastle.util.encoders.Hex;
import org.os.framework.crypto.model.Crypto;
import org.os.framework.crypto.model.AbstractStatic;

import cn.hutool.core.lang.Assert;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES
 *
 * @author
 */
public class Aes extends AbstractStatic implements Crypto<String> {

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private String password;
        private String salt;

        public Builder password(String password) {
            this.password = password;
            return this;
        }

        public Builder salt(String salt) {
            this.salt = salt;
            return this;
        }

        public Aes build() {
            return new Aes(this.password, this.salt);
        }

    }

    /**
     * 密码
     */
    private String password;

    /**
     * 盐值
     */
    private String salt;

    private static final String TRANSFORMATION = "AES/CTR/PKCS7Padding";
    private static final String ALGORITHM = "AES";
    private static final String PROVIDER = "BC";

    public Aes(String password, String salt) {
        Assert.notNull(password, "请输入密码");
        this.password = password;
        this.salt = salt == null ? "" : salt;
    }

    @SneakyThrows
    @Override
    public String encrypt(String original) {
        Md5 md5 = new Md5(salt);
        // Assuming Md5.digest returns a 16-byte array
        byte[] keyBytes = md5.digest(password).getBytes();
        byte[] ivBytes = md5.digest(new String(keyBytes)).getBytes(); 
        // 直接使用原始字节数组创建IV
        IvParameterSpec iv = new IvParameterSpec(ivBytes, 0, 16); 
        // 确保密钥也是16/24/32字节（AES支持的密钥长度）
        SecretKeySpec key = new SecretKeySpec(keyBytes, ALGORITHM);
        // 初始化加密
        Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        // 加密数据
        return Hex.toHexString(cipher.doFinal(original.getBytes()));
    }

    @SneakyThrows
    @Override
    public String decrypt(String encrypted) {
        Md5 md5 = new Md5(salt);
        // Assuming Md5.digest returns a 16-byte array
        byte[] keyBytes = md5.digest(password).getBytes();
        byte[] ivBytes = md5.digest(new String(keyBytes)).getBytes(); 
        // 直接使用原始字节数组创建IV
        IvParameterSpec iv = new IvParameterSpec(ivBytes, 0, 16);
        // 确保密钥也是16/24/32字节（AES支持的密钥长度）
        SecretKeySpec key = new SecretKeySpec(keyBytes, ALGORITHM);
        // 初始化加密
        Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        // 加密数据
        return new String(cipher.doFinal(Hex.decode(encrypted)));
    }

}
